package com.tao.service.impl;

import com.tao.mapper.ReportMapper;
import com.tao.pojo.dto.ProductStatisticDto;
import com.tao.pojo.entity.Order;
import com.tao.pojo.vo.*;
import com.tao.service.ReportService;
import com.tao.service.WorkspaceService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;


@Service
@Slf4j
public class ReportService1 implements ReportService {
    @Autowired
    ReportMapper reportMapper;
    @Autowired
    WorkspaceService workspaceService;

    @Override
    public TurnoverVo turnoverStatistic(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
        log.info("接收到的数据为start:{} end:{}", startDate, endDate);
        LocalDate today = startDate;
        log.info("today：{}", today);

        List<Double> turnoverList = new ArrayList<>();
        List<LocalDate> dateList = new ArrayList<>();

        if (startDate.isAfter(endDate)) {
            throw new RuntimeException("时间错误");
        }

        while (!today.equals(endDate)) {
            //注意当数据库当天无对应数据时sum返回null，实际想要的效果为0.0
            Double turnover = reportMapper.turnoverStatistic(LocalDateTime.of(today, LocalTime.MIN), LocalDateTime.of(today, LocalTime.MAX), Order.CONFIRMED);
            if (turnover != null)
                turnoverList.add(turnover);
            else
                turnoverList.add(0.0);

            dateList.add(today);
            //注意:错误写法 today.plusDays(1)
            //这样无法为today赋值，该函数是返回了一个新的地址
            today = today.plusDays(1);
        }

        return TurnoverVo
                .builder()
                .turnoverList(StringUtils.join(turnoverList, ","))
                .dateList(StringUtils.join(dateList, ","))
                .build();
    }

    @Override
    public UserStatisticVo userStatistic(LocalDate startDate, LocalDate endDate) {
        if (startDate.isAfter(endDate)) {
            throw new RuntimeException("时间错误");
        }
        LocalDate today = startDate;


        List<LocalDate> dateList = new ArrayList<>();
        List<Integer> totalUserList = new ArrayList<>();
        List<Integer> newUserList = new ArrayList<>();

        while (!today.equals(endDate)) {
            //注意当数据库当天无对应数据时count返回0，实际想要的效果为0,因此无需特殊转换
            newUserList.add(reportMapper.userStatistic(LocalDateTime.of(today, LocalTime.MIN), LocalDateTime.of(today, LocalTime.MAX)));
            totalUserList.add(reportMapper.userStatistic(null, LocalDateTime.of(today, LocalTime.MAX)));
            dateList.add(today);
            today = today.plusDays(1);
        }

        return UserStatisticVo.builder()
                .newUserList(StringUtils.join(newUserList, ","))
                .dateList(StringUtils.join(dateList, ","))
                .totalUserList(StringUtils.join(totalUserList, ","))
                .build();

    }

    @Override
    public OrderReportStatistic orderStatistic(LocalDate startDate, LocalDate endDate) {
        LocalDate today = startDate;

        List<LocalDate> dateList = new ArrayList<>();
        List<Integer> validOrderCountList = new ArrayList<>();
        List<Integer> orderCountList = new ArrayList<>();
        Integer total = 0;
        Integer valid = 0;
        while (!today.equals(endDate)) {
            dateList.add(today);
            Integer todayValid = reportMapper.orderStatistic(LocalDateTime.of(today, LocalTime.MIN), LocalDateTime.of(today, LocalTime.MAX), Order.CONFIRMED);
            valid = valid + todayValid;
            validOrderCountList.add(todayValid);
            Integer todayTotal = reportMapper.orderStatistic(LocalDateTime.of(today, LocalTime.MIN), LocalDateTime.of(today, LocalTime.MAX), null);
            total = total + todayTotal;
            orderCountList.add(todayTotal);
            today = today.plusDays(1);
        }
        BigDecimal rate;
        //是除法就要考虑÷0异常
        if (total.equals(0)) rate = BigDecimal.valueOf(0.0);
        else {
            rate = BigDecimal.valueOf(valid)
                    .divide(BigDecimal.valueOf(total), RoundingMode.CEILING);
        }
        return OrderReportStatistic
                .builder()
                .dateList(StringUtils.join(dateList, ","))
                .validOrderCountList(StringUtils.join(validOrderCountList, ","))
                .orderCountList(StringUtils.join(orderCountList, ","))
                .totalOrderCount(total)
                .validOrderCount(valid)
                .orderCompletionRate(rate)
                .build();
    }

    @Override
    public ProductStatisticVo productStatistic(LocalDate startDate, LocalDate endDate) {
        List<ProductStatisticDto> list = reportMapper.productStatistic(LocalDateTime.of(startDate, LocalTime.MIN), LocalDateTime.of(endDate, LocalTime.MAX));
        List<String> nameList = new ArrayList<>();
        List<Integer> numberList = new ArrayList<>();
        list.forEach(l -> {
            nameList.add(l.getName());
            numberList.add(l.getProductNumber());
        });
        return ProductStatisticVo
                .builder()
                .nameList(StringUtils.join(nameList, ","))
                .numberList(StringUtils.join(numberList, ","))
                .build();
    }

    @Override
    public void exportBusinessDate(HttpServletResponse response) throws IOException {
        //由于表格部分数据可通过已有service实现，可直接注入并通过调用对应接口
        //要求统计最近30天
        // 当天可能没过去，end为前一天即可
        LocalDate end = LocalDate.now().plusDays(-1);
        LocalDate begin = LocalDate.now().plusDays(-30);
        BusinessDataVO businessData = workspaceService.getBusinessData(LocalDateTime.of(begin, LocalTime.MIN), LocalDateTime.of(end, LocalTime.MAX));

        //通过poi写入基本模板
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
        XSSFWorkbook excel = new XSSFWorkbook(is);

        //填充数据
        XSSFSheet sheet = excel.getSheet("Sheet1");
        sheet.getRow(1).getCell(1).setCellValue("时间:" + begin + "---" + end);

        XSSFRow row = sheet.getRow(3);
        row.getCell(2).setCellValue(businessData.getTurnover());
        row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
        row.getCell(6).setCellValue(businessData.getNewUsers());

        row = sheet.getRow(4);
        row.getCell(2).setCellValue(businessData.getValidOrderCount());
        row.getCell(4).setCellValue(businessData.getUnitPrice());

        for (int i=0 ; i<30 ;i++){
            LocalDate date = begin.plusDays(i);
            //获取每天的数据
            BusinessDataVO businessData1 = workspaceService.getBusinessData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));
            row = sheet.getRow(7+i);
            row.getCell(1).setCellValue( date.toString());
            row.getCell(2).setCellValue(businessData1.getTurnover());
            row.getCell(3).setCellValue(businessData1.getValidOrderCount());
            row.getCell(4).setCellValue(businessData1.getOrderCompletionRate());
            row.getCell(5).setCellValue(businessData1.getUnitPrice());
            row.getCell(6).setCellValue(businessData1.getNewUsers());
        }
        //通过输出流下载
        ServletOutputStream os = response.getOutputStream();
        excel.write(os);


        os.close();
        is.close();
    }
}
